package com.loong.web.gp4j.encrypt.util;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

/**
 * 对称加密处理类
 * 
 * @author 张成轩
 */
public class Symmetric {

	/**
	 * 加密算法
	 */
	public enum Algorithm {

		/** DES算法 */
		DES("DES"),
		/** AES算法 */
		AES("AES");

		private String value;

		private Algorithm(String value) {

			this.value = value;
		}
	}

	/** 默认加密类型 */
	private static final Algorithm DEFAULT = Algorithm.AES;

	/**
	 * 生成随机密钥
	 * 
	 * @return 密钥
	 */
	public static String getKey() {

		// 获取密钥对象
		return getKey(DEFAULT);
	}

	/**
	 * 生成随机密钥
	 * 
	 * @param algorithm 算法
	 * @return 密钥
	 */
	public static String getKey(Algorithm algorithm) {

		// 获取密钥对象
		KeyGenerator kg;
		try {
			kg = KeyGenerator.getInstance(algorithm.value);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Symmetric variable init error: " + algorithm.name());
		}
		return Base64.encode(kg.generateKey().getEncoded());
	}

	/**
	 * 加密
	 * 
	 * @param str 明文
	 * @param key 密钥
	 * @return 密文
	 */
	public static String encrypt(String str, String key) {

		return encrypt(str, key, DEFAULT);
	}

	/**
	 * 加密
	 * 
	 * @param str 明文
	 * @param key 密钥
	 * @param algorithm 算法
	 * @return 密文
	 */
	public static String encrypt(String str, String key, Algorithm algorithm) {

		try {
			// 密钥处理对象
			Cipher cipher = Cipher.getInstance(algorithm.value);
			// 设置加密模式
			cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Base64.decode(key), algorithm.value));
			return Base64.encode(cipher.doFinal(str.getBytes("UTF-8")));

		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw new RuntimeException("Symmetric variable init error: " + algorithm.name());
		} catch (GeneralSecurityException | UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
}
